import org.devops.Constants
import org.devops.ansible
import org.devops.deploy
import org.devops.nodeTools
import org.devops.record


def call(Map map) {
    def ansible = new ansible()
    def record = new record()
    def nodeTools = new nodeTools()
    def deploy = new deploy()

    def execTime = nodeTools.getNowTime()

    pipeline {
        agent any
        // tools {
        //     jdk 'jdk8'
        //     maven 'maven'
        // }
        parameters {
            //编译部分需要的参数
            string(description: '仓库地址', name: 'GIT_URL')
            string(description: '所属环境', name: 'ENV')
            string(description: '所属服务', name: 'SERVICE')
            string(description: '应用名称', name: 'APP')
            string(description: '应用类型', name: 'APP_TYPE')
            string(description: '制品地址', name: 'ARCHIVE')
            string(description: '执行目录', name: 'EXEC_DIR')
            string(description: '编译命令', name: 'COMPILE_COMMAND')
            string(description: '编译工具版本', name: 'TOOL_VERSION')
            //部署部分需要的参数
            string(description: '部署方式', name: 'DEPLOY_TYPE')
            string(description: '自定义镜像', name: 'CUS_DOCKERFILE')
            string(description: '部署集群', name: 'DEPLOY_CLUSTER')
            string(description: '部署主机', name: 'DEPLOY_IPS')
            string(description: '部署目录', name: 'DEPLOY_DEST')
            string(description: '部署脚本', name: 'REMOTE_COMMAND')
            //补充类参数,分支,回滚版本,模式
            string(description: 'jenkins拉取git仓库代码的账号Id', name: 'GIT_CREDENTIAL_ID')
            string(defaultValue: 'origin/master', description: '分支', name: 'BRANCH')
            string(description: '回滚版本', name: 'ROLLBACK_VERSION')
            choice(choices: ['deploy', 'rollback', 'init'], description: '模式', name: 'MOD')
        }
        options {
            timestamps() // 输出构建日志打印时间信息
            timeout(time: 60, unit: 'MINUTES') // 设置构建超时时间
            buildDiscarder(logRotator(numToKeepStr: '5')) // 设置历史构建保留次数
        }
        stages {
            stage('git clone') {
                steps {
                    script {
                        def gitCredentialId = "${params.GIT_CREDENTIAL_ID}"
                        if (gitCredentialId == null || gitCredentialId == "") {
                            gitCredentialId = Constants.GIT_CREDENTIAL_ID
                        }
                        String branch = "$BRANCH".replaceAll("origin/", "")
                        git branch: "${branch}", credentialsId: "${gitCredentialId}", url: "${GIT_URL}"
                    }
                }
            }
            stage('编译') {
                when {
                    environment name: 'MOD', value: 'deploy'
                }
                steps {
                    script {
                        if (TOOL_VERSION && TOOL_VERSION != "") {
                            TOOL_VERSION.split(",").each { t ->
                                toolHome = "${tool "${t}"}"
                                //加载工具地址
                                echo "加载: ${toolHome}"
                                env.PATH = "${toolHome}/bin:${env.PATH}"
                                echo "PATH: ${env.PATH}"
                            }
                        } else {
                            echo "未加载工具"
                        }

                        sh "${COMPILE_COMMAND}"
                    }
                }
            }
            stage('部署') {
                when {
                    environment name: 'MOD', value: 'deploy'
                }
                steps {
                    script {
                        String orgBranch = "$BRANCH".replaceAll("origin/", "")
                        String branch = orgBranch.replaceAll("_", "-").replaceAll("/", "-")
                        String commit = sh(returnStdout: true, script: "git rev-parse --short HEAD").trim()
                        if (params.DEPLOY_TYPE == "k8s") {
                            def IMAGE_URL = "${Constants.HARBOR_PROJECT}"
                            if ("$SERVICE" != "") {
                                IMAGE_URL += "/$SERVICE"
                            }
                            IMAGE_URL += "/$APP"
                            def IMAGE_TAG = "${branch}-${commit}-$BUILD_NUMBER"
                            def IMAGE_NAME = "${IMAGE_URL}:${IMAGE_TAG}"
                            echo "1. 项目${APP}镜像名称: $IMAGE_NAME"

                            def str = "${ARCHIVE}"
                            def lastIndex = str.lastIndexOf("/")
                            def fileName = (lastIndex != -1) ? str.substring(lastIndex + 1) : str

                            // 迁移archive文件到dockerfile目录
                            sh """mkdir -p ${workspace}/${Constants.JENKINS_DOCKERFILES_DIR}"""
                            sh """rm -rf ${workspace}/${Constants.JENKINS_DOCKERFILES_DIR}/${fileName}"""
                            sh """cp -rp ${ARCHIVE} ${workspace}/${Constants.JENKINS_DOCKERFILES_DIR}/${fileName}"""


                            echo "2.项目$APP docker编译"
                            sh """mkdir -p ${Constants.JENKINS_DOCKERFILES_DIR}"""

                            if (params.CUS_DOCKERFILE && params.CUS_DOCKERFILE != "") {
                                // 自定义dockerfile 写入编译目录
                                writeFile file: "${workspace}/${Constants.JENKINS_DOCKERFILES_DIR}/${APP}", text: "${params.CUS_DOCKERFILE}"
                            } else {
                                if (params.APP_TYPE == "java") {
                                    defineJavaDefaultDockerfile("${Constants.DEFAULT_JAVA_RUN_IMAGE}", "${workspace}/${Constants.JENKINS_DOCKERFILES_DIR}", "${APP}", "${fileName}")
                                } else if (params.APP_TYPE == "nginx") {
                                    defineNginxDefaultDockerfile("${Constants.DEFAULT_NGINX_RUN_IMAGE}", "${workspace}/${Constants.JENKINS_DOCKERFILES_DIR}", "${APP}", "${fileName}")
                                }
                            }

                            sh """docker build -t $IMAGE_NAME -f ${workspace}/$Constants.JENKINS_DOCKERFILES_DIR/$APP  ${workspace}/$Constants.JENKINS_DOCKERFILES_DIR"""

                            echo "3.项目$APP docker 上传"
                            sh """docker push  $IMAGE_NAME"""


                            deploy.baseNodeDeployK8sApp("${APP}", IMAGE_URL, IMAGE_TAG)

                            //上传部署信息到project-info(记录每次部署信息)服务上,并将返回结果拼接成需要删除的node
                            record.recordImageProjectInfo(execTime, Constants.PROJECT_BASE_URL, "${APP}", "")
                        } else if (params.DEPLOY_TYPE == "node") {
                            // 使用node 部署
                            //1. 将制品文件放入到编译目录,并添加额外文件
                            sh "mkdir -p ${workspace}/${Constants.DEPLOY_CONF_DIR}"
                            sh "rm -rf ${workspace}/${Constants.DEPLOY_CONF_DIR}/*"
                            dir("${workspace}/${Constants.DEPLOY_CONF_DIR}") {
                                def processedArchive = "${ARCHIVE}".replaceAll("\\./", "")
                                sh "mv ${workspace}/${processedArchive} ./"
                                sh "find ./ -name *.sh -exec chmod +x {} \\;"
                                sh "tar -cf ${Constants.ANSIBLE_STORE_FILE} * --exclude=Jenkinsfile"
                            }

                            //通过ips判断要上传到哪
                            Map ipMap = nodeTools.processIpMap("${DEPLOY_IPS}".split(","))
                            def ansibleNames = ipMap.keySet()

                            //上传到ansible服务器
                            String remoteDir = sh(returnStdout: true, script: "date +%Y%m%d%H%M%S").trim()
                            def fullPath = "/data/app_repos/${ENV}"
                            if ("${SERVICE}" != "") {
                                fullPath += "/${SERVICE}"
                            }
                            fullPath += "/${APP}/${remoteDir}"
                            echo "ansibleNames: ${ansibleNames}"
                            echo "fullPath: ${fullPath}"
                            for (ansibleName in ansibleNames) {
                                /*1.在ansible服务器上建立目录*/ nodeTools.remoteExec(ansibleName, "mkdir -p ${fullPath}")
                                //2.上传文件到ansible服务器
                                nodeTools.exeSshPublisher(ansibleName, "", "${Constants.DEPLOY_CONF_DIR}/${Constants.ANSIBLE_STORE_FILE}", fullPath, true)
                                //3.在ansible服务器上执行
                                ansible.ansibleExec(ipMap, ansibleName, "${DEPLOY_IPS}", Constants.ANSIBLE_STORE_FILE, "${DEPLOY_DEST}", remoteDir, "${REMOTE_COMMAND}")
                            }

                            //上传部署信息到project-info(记录每次部署信息)服务上,并将返回结果拼接成需要删除的node
                            record.recordProjectInfo(execTime, Constants.PROJECT_BASE_URL, remoteDir, Constants.ANSIBLE_STORE_FILE, ansibleNames)
                        } else {
                            error "不支持的部署方式"
                        }

                    }
                }
            }
            stage("回滚") {
                when {
                    environment name: 'MOD', value: 'rollback'
                }
                steps {
                    script {
                        def rollbackVersion = "${params.ROLLBACK_VERSION}"
                        def split = rollbackVersion.split("\\|")
                        if (split.size() == 0) {
                            error "请选择要回滚的版本"
                        }

                        def r = record.getProjectInfoByBuildNumber(Constants.PROJECT_BASE_URL, split[0])
                        if (r.exe_type == "node" && r.dir != "") {
                            Map ipMap = nodeTools.processIpMap("${DEPLOY_IPS}".split(","))
                            def ansibleNames = ipMap.keySet()
                            for (ansibleName in ansibleNames) {
                                ansible.ansibleExec(ipMap, ansibleName, "${DEPLOY_IPS}", Constants.ANSIBLE_STORE_FILE, "${DEPLOY_DEST}", r.dir, "${REMOTE_COMMAND}")
                            }
                        } else if (r.exe_type == "k8s") {
                            def IMAGE_PRIFIX = "${Constants.HARBOR_PROJECT}"
                            if ("$SERVICE" != "") {
                                IMAGE_PRIFIX += "/$SERVICE"
                            }
                            IMAGE_PRIFIX += "/$APP"
                            def IMAGE_TAG = "${r.branch}-${r.commit}-${r.build_number}"
                            deploy.baseNodeDeployK8sApp("${APP}", IMAGE_PRIFIX, IMAGE_TAG)
                        }
                    }
                }
            }
        }
    }
}


def defineJavaDefaultDockerfile(RUN_IMAGE, jenkinsDockerfileDir, app, src) {
    String path = jenkinsDockerfileDir + "/" + app
    String dockerfile = '''    
FROM $RUN_IMAGE        
        
ENV TZ=Asia/Shanghai
ENV JAVA_OPTS=""

RUN mkdir -p /app

WORKDIR /app

EXPOSE 8080

ADD $src ./app.jar

CMD java \$JAVA_OPTS -jar app.jar
'''

    dockerfile = dockerfile.replace("\$RUN_IMAGE", RUN_IMAGE).replace("\$src", src)
    writeFile file: "${path}", text: "${dockerfile}"
}


def defineNginxDefaultDockerfile(RUN_IMAGE, jenkinsDockerfileDir, app, src) {
    String path = jenkinsDockerfileDir + "/" + app
    String dockerfile = '''    
FROM $RUN_IMAGE

ADD $src /usr/share/nginx/html/$src
'''

    dockerfile = dockerfile.replace("\$RUN_IMAGE", RUN_IMAGE).replace("\$src", src)
    writeFile file: "${path}", text: "${dockerfile}"
}
